package dragon

import (
	"http"
	"template"
	"time"
	"os"
	"strconv"
	"math"
	"strings"

	"appengine"
	"appengine/datastore"
)

type article struct {
	Title   string
	Content []byte
	Date    datastore.Time
	Kind    string
}

type article4tmpl struct {
	Title   string
	Content []byte
	Date    string
	Kind    string
	Key	string
}

func handleArticles(w http.ResponseWriter, r *http.Request) {
	const pagelenPath = len(newspageURL)
	const limit = 5
	var cs []*counters
	var page = 1
	var a []*article
	var q *datastore.Query
	var ks []*datastore.Key
	var err os.Error
	var mapa map[string]interface{}

	c := appengine.NewContext(r)
	if strings.HasPrefix(r.URL.Path, newspageURL) {
		if !isAllDigits(r.URL.Path[pagelenPath:]) {
			http.Redirect(w, r, newspageURL+"1", http.StatusFound)
			return
		}
		page, err = strconv.Atoi(r.URL.Path[pagelenPath:])
		if err != nil {
			http.Redirect(w, r, newspageURL+"1", http.StatusFound)
			return
		}
		q = datastore.NewQuery("article").Order("-Date").
			Filter("Kind =", "wiesci").
			Offset((page-1)*limit).
			Limit(limit)
	} else {
		q = datastore.NewQuery("article").Order("Date").
			Filter("Kind =", r.URL.Path[1:])
	}
	ks, _ = q.GetAll(c, &a)

	if strings.HasPrefix(r.URL.Path, newspageURL) {
		q = datastore.NewQuery("counters").Filter("Kind =", "wiesci").Limit(1)
		csks, _ := q.GetAll(c, &cs)
		if len(csks) == 0 {
			addCounter("wiesci", c)
			q.GetAll(c, &cs)
		}
	}

	a4t := make([]article4tmpl, len(a))

	for k := range ks {
		a4t[k].Title = a[k].Title
		a4t[k].Content = a[k].Content
		date := a[k].Date.Time()
		a4t[k].Date = prettyDate(date)
		a4t[k].Key = ks[k].Encode()
	}
    
	ts := new(template.Set)
	troot, _ := template.New("root").
			Funcs(template.FuncMap{
				"date": stuffDate,
			}).
			ParseFile("templates/root.html")
	tarticles := template.New("content")
	if strings.HasPrefix(r.URL.Path, newspageURL) {
		funcs := template.FuncMap{
			"markdown": markdownCommon,
			"selector": selector,
		}
		mapa = map[string]interface{} {
			"Entries": a4t,
			"Site": count(c, r, w),
			"Mapa": map[string]interface{} {
				"Pages": int(math.Ceil(float64(cs[0].Count)/limit)),
				"Page": page,
			},
		}
		tarticles.Funcs(funcs).ParseFile("templates/news.html")
	} else {
		mapa = map[string]interface{} {
			"Site": count(c, r, w),
			"Entries": a4t,
		}
		tarticles.ParseFile("templates/articles.html")
	}
	ts.Add(troot, tarticles)
	ts.Execute(w, "root", mapa)
}

func handleAdminArticles(w http.ResponseWriter, r *http.Request) {
	var a []*article
	var q *datastore.Query
	var ks []*datastore.Key

	c := appengine.NewContext(r)
	q = datastore.NewQuery("article").Order("Kind").Order("-Date")
	ks, _ = q.GetAll(c, &a)

	a4t := make([]article4tmpl, len(a))

	for k := range ks {
		a4t[k].Title = a[k].Title
		a4t[k].Kind = a[k].Kind
		a4t[k].Key = ks[k].Encode()
	}
    
	ts := new(template.Set)
	tadmin, _ := template.New("admin").ParseFile("templates/admin.html")
	tarticles := template.New("content")
	tarticles.ParseFile("templates/admin-articles.html")
	ts.Add(tadmin, tarticles)
	ts.Execute(w, "admin", a4t)
}

func handleArticleAdd(w http.ResponseWriter, r *http.Request) {
	const lenPath = len(admarticleaddURL)

        if len(r.URL.Path[lenPath:]) < 1 {
               	http.Redirect(w, r, "/", http.StatusFound)
               	return
        }

	if r.Method != "POST" {
		ts := new(template.Set)
		tadmin, _ := template.New("admin").
			ParseFile("templates/admin.html")
		tarticleadd, _ := template.New("content").
			ParseFile("templates/article-add.html")
		ts.Add(tadmin, tarticleadd)
		ts.Execute(w, "admin", map[string] string { "Kind": r.URL.Path[lenPath:], })
		return
	}

	c := appengine.NewContext(r)
	r.ParseForm()
	a := &article{
        	Title:   r.FormValue("title"),
        	Kind:    r.URL.Path[lenPath:],
		Content: []byte(r.FormValue("content")),
		Date:    datastore.SecondsToTime(time.Seconds()),
	}
	_, err := datastore.Put(c, datastore.NewIncompleteKey(c, "article", nil), a)
	if err != nil {
		http.Redirect(w, r, "/static/err.html", http.StatusFound)
		return
	}
	if r.URL.Path[lenPath:] == "wiesci" {
		updateCount("wiesci", c, true);
	}
	http.Redirect(w, r, adminURL, http.StatusFound)
}

func handleArticleShow(w http.ResponseWriter, r *http.Request) {
	const lenPath = len(articleURL)
	var a article

	c := appengine.NewContext(r)
        k, err := datastore.DecodeKey(r.URL.Path[lenPath:])
        if err != nil {
                http.Redirect(w, r, "/", http.StatusFound)
                return
        }
        datastore.Get(c, k, &a)

	funcs := template.FuncMap{
		"markdown": markdownCommon,
	}
	mapa := map[string]interface{} {
		"Site": count(c, r, w),
		"Entries": a,
	}

	ts := new(template.Set)
	troot, _ := template.New("root").
			Funcs(template.FuncMap{
				"date": stuffDate,
			}).
			ParseFile("templates/root.html")
	tarticleshow, _ := template.New("content").Funcs(funcs).
		ParseFile("templates/article-show.html")
	ts.Add(troot, tarticleshow)
	ts.Execute(w, "root", mapa)
}

func handlePage(w http.ResponseWriter, r *http.Request) {
	var a []*article

	c := appengine.NewContext(r)
	q := datastore.NewQuery("article").Order("-Date").
		Filter("Kind =", r.URL.Path[1:])
	ks, _ := q.GetAll(c, &a)

	a4t := make([]article4tmpl, len(a))

	for k := range ks {
		a4t[k].Title = a[k].Title
		a4t[k].Content = a[k].Content
		a4t[k].Kind = a[k].Kind
		date := a[k].Date.Time()
		a4t[k].Date = prettyDate(date)
		a4t[k].Key = ks[k].Encode()
	}
    
	funcs := template.FuncMap{
		"markdown": markdownCommon,
	}
	mapa := map[string]interface{} {
		"Site": count(c, r, w),
		"Entries": a4t,
	}

	ts := new(template.Set)
	troot, _ := template.New("root").
			Funcs(template.FuncMap{
				"date": stuffDate,
			}).
			ParseFile("templates/root.html")
	tarticleshow, _ := template.New("content").Funcs(funcs).
		ParseFile("templates/page.html")
	ts.Add(troot, tarticleshow)
	ts.Execute(w, "root", mapa)
}

func handleAdminPage(w http.ResponseWriter, r *http.Request) {
	var a []*article

	c := appengine.NewContext(r)
	q := datastore.NewQuery("article").Order("-Date").
		Filter("Kind =", r.URL.Path[1:])
	ks, _ := q.GetAll(c, &a)

	a4t := make([]article4tmpl, len(a))

	for k := range ks {
		a4t[k].Title = a[k].Title
		a4t[k].Content = a[k].Content
		date := a[k].Date.Time()
		a4t[k].Date = prettyDate(date)
		a4t[k].Key = ks[k].Encode()
	}
    
	funcs := template.FuncMap{
		"markdown": markdownCommon,
	}

	ts := new(template.Set)
	tadmin, _ := template.New("admin").ParseFile("templates/admin.html")
	tpageshow, _ := template.New("content").Funcs(funcs).
		ParseFile("templates/page.html")
	ts.Add(tadmin, tpageshow)
	ts.Execute(w, "admin", a4t)
}

func handleArticleEdit(w http.ResponseWriter, r *http.Request) {
	const lenPath = len(admarticleeditURL)
	k, err := datastore.DecodeKey(r.URL.Path[lenPath:])
        if err != nil {
               	http.Redirect(w, r, "/", http.StatusFound)
               	return
        }

	if r.Method != "POST" {
		var a article
		var a4t article4tmpl

		c := appengine.NewContext(r)
		datastore.Get(c, k, &a)

		a4t.Title = a.Title
		a4t.Content = a.Content
		a4t.Kind = a.Kind
		a4t.Date = strconv.Itoa64(a.Date.Time().Seconds())
		a4t.Key = k.Encode()

		ts := new(template.Set)
		tadmin, _ := template.New("admin").ParseFile("templates/admin.html")
		tarticleedit, _ := template.New("content").
			ParseFile("templates/article-edit.html")
		ts.Add(tadmin, tarticleedit)
		ts.Execute(w, "admin", a4t)
		return
	}

	c := appengine.NewContext(r)
	r.ParseForm()
	date, _ := strconv.Atoi64(r.FormValue("date"))
	a := &article{
        	Title:   r.FormValue("title"),
        	Kind:    r.FormValue("kind"),
		Content: []byte(r.FormValue("content")),
		Date:    datastore.SecondsToTime(date),
	}
	datastore.Delete(c, k)
	datastore.Put(c, k, a)
	http.Redirect(w, r, admarticlesURL, http.StatusFound)
}

func handleArticleDelete(w http.ResponseWriter, r *http.Request) {
	const lenPath = len(admarticledelURL)

	c := appengine.NewContext(r)
	k, err := datastore.DecodeKey(r.URL.Path[lenPath:])
	if err != nil {
		http.Redirect(w, r, "/", http.StatusFound)
		return
	}
	err = datastore.Delete(c, k)
	if err != nil {
		http.Redirect(w, r, "/static/err.html", http.StatusFound)
		return
	}
	if r.URL.Path[lenPath:] == "wiesci" {
		updateCount("wiesci", c, false);
	}
	http.Redirect(w, r, adminURL, http.StatusFound)
}
